# -*- coding: utf-8 -*-
'''
Created on 20.11.2010
Copyright (C) 2010 Alexander S. Razzhivin ( site http://httpbots.com )

#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
# 
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
# 
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
'''

from pprint import pprint
"""Subclass of MainFrameBase, which is generated by wxFormBuilder."""
import wx
import gui
from pyvkapi import PyVkApi
from grabaudio import download_record, report, LAST_PERCENT_DOWN, check_updates
from urllib2 import HTTPError
import threading
import webbrowser
import os

# Implementing MainFrameBase
class MainFrame( gui.MainFrameBase ):
  
  songs4download = {}
  records = {}
  version = '10'
  
    
  def __init__( self, parent ):
    gui.MainFrameBase.__init__( self, parent )
    favicon = wx.Icon('vkag_16x16.ico', wx.BITMAP_TYPE_ICO, 16, 16)
    self.SetIcon(favicon)
    self.m_checkList_artist.Clear()
    self.m_checkList_song.Clear()
    self.Bind(EVT_GRAB_INFO, self.OnGrabInfo)
    self.Bind(EVT_GRAB_REP, self.OnGrabReport)
    ver_url = check_updates(self.version)
    self.default_path_to_down = os.path.join(os.getcwd(),"downloaded")
    if ver_url:
      self.m_link_update.SetLabel(u"Скачать последнюю версию VK Audio Grabber %s.%s" % (ver_url[0][0], ver_url[0][1]))
      self.m_link_update.SetURL(ver_url[1])
    self.m_dirPicker.SetPath(self.default_path_to_down)

  
  def __cut_nums_from_str(self, s):
    import string
    return filter(lambda c: c in string.digits, s)
  
  def vk_connect(self):
    email = self.m_text_login.GetValue()
    password = self.m_text_pass.GetValue()
    api_id = self.__cut_nums_from_str(self.m_text_appid.GetValue())
    uid = self.__cut_nums_from_str(self.m_text_uid.GetValue())
    fuid = self.__cut_nums_from_str(self.m_text_fid.GetValue())
    gid = self.__cut_nums_from_str(self.m_text_gid.GetValue())
    
    try:
      self.vkapi = PyVkApi(email, password, uid, api_id)
      if fuid:
        uid = fuid
      self.records = self.vkapi.call(['method=audio.get', 'uid=%s' % uid, 'gid=%s' % gid])
    except HTTPError as e:
      wx.MessageBox(u"Возникла ошибка при подключении к сайту ВКонтакте. Необходимо как минимум заполнить поля: Логин, Пароль, App ID и Ваш ID. Инструкция по настройке на сайте http://httpbots.com")
      print e
    except IndexError as e:
      wx.MessageBox(u"Возникли проблемы при загрузке списка. Попробуйте ещё раз загрузить список.")
      print e

  def m_button_loadlistOnButtonClick( self, event ):
    self.vk_connect()
      
    self.m_checkList_artist.Clear()
    
    choices = []
    for r in self.records:
      if choices.count(r['artist']):  continue
      choices.append(r['artist'])
    self.m_checkList_artist.Set(choices)
    self.m_button_grab.Enable(True)
  
  def m_checkList_artistOnCheckListBox( self, event ):
    if self.m_checkList_artist.GetSelection() == wx.NOT_FOUND: return
    #wx.MessageBox(self.m_checkList_artist.Items[self.m_checkList_artist.GetSelection()])
    
    # добавим композиции для выбора    
    choices = []
    for r in self.records:
      if r['artist'] != self.m_checkList_artist.Items[self.m_checkList_artist.GetSelection()]:  continue
      choices.append(r['title'])
    self.m_checkList_song.Set(choices)
    
    # отметить ранее выбранные композиции
    checkedIndexes = []
    for i,r in enumerate(choices):
      if r in self.songs4download.keys():
        checkedIndexes.append(i)

    self.m_checkList_song.SetChecked(checkedIndexes)
    
    if self.m_checkList_artist.IsChecked(event.Selection):
      self.m_checkList_song.SetChecked(range(0, len(self.m_checkList_song.Items)))
      self.add_chkd_song_url()
    
  def m_button_unselartistsOnButtonClick( self, event ):
    self.SetUncheckedCheckList(self.m_checkList_artist, range(0,len(self.m_checkList_artist.Items)))
  
  def SetUncheckedCheckList(self, checkList, indexes):
    for i in indexes:
        assert 0 <= i < checkList.Count, "Index (%s) out of range" % i
    for i in indexes:
        checkList.Check(i, check=False)
  
  def rm_chkd_songs_urls(self, checkList, indexes):
    for i in indexes:
        del self.songs4download[checkList.Items[i]]
  
  def m_checkList_artistOnCheckListBoxToggled( self, event ):
    # if artist is checked
    if self.m_checkList_artist.IsChecked(event.Selection):
      self.m_checkList_song.SetChecked(range(0, len(self.m_checkList_song.Items)))
      self.add_chkd_song_url()
    else: 
      self.SetUncheckedCheckList(self.m_checkList_song, range(0, len(self.m_checkList_song.Items)))
      self.rm_chkd_songs_urls(self.m_checkList_song, range(0, len(self.m_checkList_song.Items)))
  
  def add_chkd_song_url(self):
    chkdSongs = self.m_checkList_song.GetCheckedStrings()
    for r in self.records:
      if r['title'] in chkdSongs:
        self.songs4download.setdefault(r['title'])
        self.songs4download[r['title']] = 1
    #pprint(self.songs4download)

  def m_checkList_songOnCheckListBoxToggled( self, event ):

    if self.m_checkList_song.IsChecked(event.Selection):
      self.add_chkd_song_url()
    else:
      del self.songs4download[self.m_checkList_song.Items[event.Selection]]

 
  def m_button_grabOnButtonClick( self, event ):
    
    self.m_button_stop.Enable(True)	
    path = self.m_dirPicker.GetPath()
    if not path:  path = self.default_path_to_down
    
    self.grab_thread = GrabThread(self, self.records, self.songs4download, path)
    self.grab_thread.start()
  
  def OnGrabInfo(self, event):  
    self.m_textCtrl_downProc.Value += event.GetInfo()

  def OnGrabReport(self, event):
    self.m_gauge.SetValue(int(event.GetInfo()))

    
  def m_button_stopOnButtonClick( self, event ):
    self.grab_thread.terminate()
    self.m_textCtrl_downProc.Value += u' Останавливаемся... %s' % chr(10)
    
  def m_menuItem_friendsOnMenuSelection( self, event ):
    fdlg = FriendsDialogExt(self)
    fdlg.ShowModal()
    fdlg.Destroy()
  
  def m_menuItem_aboutOnMenuSelection( self, event ):
    adlg = gui.AboutDialog(self)
    adlg.ShowModal()
    adlg.Destroy()
  
  def m_menuItem_exitOnMenuSelection( self, event ):
    self.Close()
  
  def m_menuItem_siteOnMenuSelection( self, event ):
    webbrowser.open_new("http://httpbots.com")
    
  def m_menuItem_groupLinkOnMenuSelection( self, event ):
    webbrowser.open_new("http://vkontakte.ru/club21835090")
    

class FriendsDialogExt (gui.FriendsDialog):


  def __init__( self, parent ):
    gui.FriendsDialog.__init__(self,parent)
    self.parent = parent
    
    for col, text in enumerate(['ID', u'Имя',u'Фамилия']):
      self.m_listCtrl_fids.InsertColumn(col, text)
    
    self.parent.vk_connect()
    fdata = self.parent.vkapi.call(['method=friends.get', 'fields=uid,first_name,last_name'])
    for i, r in enumerate(fdata):
      self.m_listCtrl_fids.InsertStringItem(i, str(r['uid']))
      self.m_listCtrl_fids.SetStringItem(i, 1, r['first_name'])
      self.m_listCtrl_fids.SetStringItem(i, 2, r['last_name'])  
    
  def m_listCtrl_fidsOnListItemSelected( self, event ):
    self.parent.m_text_fid.SetValue(self.m_listCtrl_fids.GetItemText(event.m_itemIndex))

                     
EVT_GRAB = wx.NewEventType()
EVT_GREP = wx.NewEventType()
EVT_GRAB_INFO = wx.PyEventBinder(EVT_GRAB, 1)
EVT_GRAB_REP = wx.PyEventBinder(EVT_GREP, 1)


class GrabInfoEvent(wx.PyCommandEvent):

    def __init__(self, etype, eid, info=None):
        """Creates the event object"""
        wx.PyCommandEvent.__init__(self, etype, eid)
        self.info = info

    def GetInfo(self):
        """Returns the value from the event.
        @return: the value of this event
        """
        return self.info

class GrabThread(threading.Thread):
  def __init__(self, parent, records, songs4download, pathToSave):
    threading.Thread.__init__(self)
    self.records = records
    self.path = pathToSave
    self.parent = parent
    self.songs4down = songs4download
    self._terminate = False
  
  def terminate(self):
    self._terminate = True
    
    
  def run(self):
    for r in self.records:
      if self._terminate:  
        self.reporthook(0, 0, 1) # reset progress barr
        break

      if r['title'] in self.songs4down.keys():
        info =  r['title']
        info += download_record(self.path, r, self.reporthook)
        info = "%s %s" % (info, chr(10))
        evt = GrabInfoEvent(EVT_GRAB, -1, info)
        wx.PostEvent(self.parent, evt)
        
  def reporthook(self, count, blockSize, totalSize):
    r = report(count, blockSize, totalSize)
    if r: 
      evt = GrabInfoEvent(EVT_GREP, -1, r)
      wx.PostEvent(self.parent, evt)
 
